#include "EditorScreen.h"

using namespace SDL::UTILS;

EditorArgs::EditorArgs(SDL_Surface* _screen, SDL_Event* _event,
					   Surface& _loadedBackground,
					   Bloc*& _currentBloc, BlocManager& _blocs, bool& _showGrid)
	: ScreenArgs(_screen, _event), LoadedBackground(_loadedBackground),
	CurrentBloc(_currentBloc), Blocs(_blocs), ShowGrid(_showGrid)
{
}

EditorArgs::~EditorArgs()
{
}

EditorScreen::EditorScreen() : IScreen(), m_position(24, 112),
	m_gridLimits(24, 112, 800, 560), m_cursor("tilescursor.png")
{
	this->InitGrid();
	m_surface.SetSurface(SDL_CreateRGBSurface(SDL_HWSURFACE, 800, 600, 32, 0, 0, 0, 0));
}

EditorScreen::~EditorScreen()
{
}

void EditorScreen::Draw(IArgs* _datas)
{
	EditorArgs* ea = dynamic_cast<EditorArgs*>(_datas);

	SDL_FillRect(m_surface.GetSurface(), NULL, 0);

	ea->LoadedBackground.BlitSurface(NULL, m_surface.GetSurface(), NULL);
	if (ea->ShowGrid == true)
		m_grid.BlitSurface(NULL, m_surface.GetSurface(), NULL);
	ea->Blocs.Draw(m_surface.GetSurface());
	
	int x = 0, y = 0;
	SDL_GetMouseState(&x, &y);
	if (Rect::IsInArea(Rect(x, y), m_gridLimits))
		this->DrawCursor(ea);

	m_surface.BlitSurface(NULL, ea->Screen, &m_position);
}

void EditorScreen::Exec(IArgs* _datas)
{
	EditorArgs* ea = dynamic_cast<EditorArgs*>(_datas);

	int x = 0, y = 0;
	Uint8 button = SDL_GetMouseState(&x, &y);
	if (Rect::IsInArea(Rect(x, y), m_gridLimits))
		this->MouseEvents(button, x, y, ea);
	else
		SDL_ShowCursor(1);
	
	if (ea->Event->type == SDL_MOUSEBUTTONUP)
		this->WheelMove(ea);
}

bool EditorScreen::Manage(ScreenManager::Element* _caller, IArgs* _args)
{
	return (true);
}

void EditorScreen::InitGrid()
{
	SDL_Surface* s = SDL_CreateRGBSurface(SDL_HWSURFACE,
		m_gridLimits.GetW(), m_gridLimits.GetH() + 1, 32, 0, 0, 0, 0);
	SDL_FillRect(s, NULL, 0xFF00FF);

	for (int y = 0; y < s->h; y++)
	{
		if (y % 16 == 0)
			for (int x = 0; x < s->w; x++)
				Surface::SetPixel(s, 0, x, y);
		else
			for (int x = 0; x < s->w; x += 32)
				Surface::SetPixel(s, 0, x, y);
	}
	m_grid.SetSurface(s);
	m_grid.SetColorKey(0xFF00FF);
}

void EditorScreen::MouseEvents(Uint8 _button, int _x, int _y, EditorArgs* _args)
{
	SDL_ShowCursor(0);
	SDL_Rect r = { (_x - m_gridLimits.GetX()) - 16,
					(_y - m_gridLimits.GetY()) - 8,
					0, 0 };
	r.x = (r.x / 32) * 32;
	r.y = (r.y / 16) * 16;
	m_cursorPosition = r;
	if (_args->CurrentBloc != NULL)
	{
		if (_button & SDL_BUTTON_LMASK)
			this->LeftButton(_args, r);
		else if (_button & SDL_BUTTON_RMASK)
			this->RightButton(_args, r);
		else if (_button & SDL_BUTTON_MMASK)
			this->MiddleButton(_args, r);
	}
	m_cursor.SetPosition(m_cursorPosition);
}

void EditorScreen::LeftButton(EditorArgs* _args, SDL_Rect& _r)
{
	Bloc* b = _args->Blocs.GetAt(_r.x, _r.y);
	if (b == NULL)
		_args->Blocs.Add(_args->CurrentBloc->GetType(), Rect(_r.x, _r.y));
	else
	{
		if (b->GetType() != _args->CurrentBloc->GetType())
		{
			_args->Blocs.Remove(b->GetType(), b);
			_args->Blocs.Add(_args->CurrentBloc->GetType(), Rect(_r.x, _r.y));
		}
	}
}

void EditorScreen::RightButton(EditorArgs* _args, SDL_Rect& _r)
{
	Bloc* b = _args->Blocs.GetAt(_r.x, _r.y);
	if (b != NULL)
		_args->Blocs.Remove(b->GetType(), b);
}

void EditorScreen::MiddleButton(EditorArgs* _args, SDL_Rect& _r)
{
	Bloc* b = _args->Blocs.GetAt(_r.x, _r.y);
	if (b == NULL)
		return ;
	else
		_args->CurrentBloc = _args->Blocs.GetOriginals()[b->GetType()];
}

void EditorScreen::WheelMove(EditorArgs* _args)
{
	if (_args->CurrentBloc != NULL)
	{
		if (_args->Event->button.button == SDL_BUTTON_WHEELDOWN ||
			_args->Event->button.button == SDL_BUTTON_WHEELUP)
		{
			int current = 0;
			std::map<std::string, Bloc*>& originals = _args->Blocs.GetOriginals();
			std::map<std::string, Bloc*>::iterator it = originals.begin();
			std::map<std::string, Bloc*>::iterator last = originals.begin();
			std::map<std::string, Bloc*>::iterator next = originals.begin();
			bool oups = false;
			for (; it != originals.end(); ++it, current++)
			{
				next++;
				if (it->second == _args->CurrentBloc)
				{
					if (_args->Event->button.button == SDL_BUTTON_WHEELDOWN)
					{
						if (last == originals.begin() && oups == false)
							while (it != originals.end())
								last = it++;
					}
					else
					{
						if (next == originals.end())
							last = originals.begin();
						else
							last = next;
					}
					_args->CurrentBloc = last->second;
					return ;
				}
				oups = true;
				last = it;
			}
		}
	}
}

void EditorScreen::DrawCursor(EditorArgs* _args)
{
	if (_args->CurrentBloc != NULL)
	{
		SDL_Rect srcrect;
		_args->CurrentBloc->GetCurrentSprite()->CurrentFrame.ToSDLRect(srcrect);
		srcrect.x = 0;
		srcrect.y = 0;
		SDL_BlitSurface(_args->CurrentBloc->GetSurface()->GetSurface(), &srcrect,
						m_surface.GetSurface(), &m_cursorPosition);
	}
	m_cursor.Draw(m_surface.GetSurface());
}
